package ru.beta2.testyard;

import ru.beta2.testyard.config.Configuration;
import ru.beta2.testyard.engine.ScenarioEngine;
import ru.beta2.testyard.engine.hotspot.HotspotConnector;
import ru.beta2.testyard.TestyardHookMBean;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;

/**
 * Testyard framework enrty point (main class, bootstrapper).
 * Provide {@link Scenario} object and management of server app through JMX.
 * <br/>
 * User: Inc
 * Date: 16.06.2008
 * Time: 22:56:05
 */
public class TestYard
{

    private final Configuration cfg;

    private TestyardHookMBean hook;

    private JMXConnector jmxc;

    /**
     * Create testyard with given configuration and establish JMX connection to server app.
     * <br/>
     * JMX connection established only in case when both {@code cfg.getJMXServiceURL()}
     * and {@code cfg.getTestyardHookMBeanName()} is not null. So if you don't need to use JMX management, simply
     * do not assign values to these configuration fields. 
     * @param cfg custom configuration
     */
    public TestYard(Configuration cfg)
    {
        this.cfg = cfg;

        if (cfg.getJMXServiceURL() != null && cfg.getTestyardHookMBeanName() != null) {
            try {
                jmxc = JMXConnectorFactory.connect(new JMXServiceURL(cfg.getJMXServiceURL()));
                MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

                hook = (TestyardHookMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, new ObjectName(cfg.getTestyardHookMBeanName()), TestyardHookMBean.class, false);
            }
            catch (Exception e) {
                throw new RuntimeException("Error obtaining testyard hook", e);
            }
        }
    }

    /**
     * Release all previously allocated resources. Tests tearDown method is a good place to call this method.
     * @throws IOException
     */
    public void close() throws IOException
    {
        if (jmxc != null) {
            jmxc.close();
            jmxc = null;
        }
    }

    /**
     * Clean up server application state. Use this method in tests setUp.  
     */
    public void clearDatabase()
    {
        if (hook != null) {
            hook.removeAllManagedObjects();
        }
    }

    /**
     * Create and return new {@link Scenario} implementation
     * @return new {@link Scenario} object
     */
    public Scenario getScenario()
    {
        HotspotConnector hotspot = new HotspotConnector(cfg);
        return new ScenarioEngine(hotspot, cfg);
    }

}
